﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace XChip_Common
{
   public static   class BitsHelp
    {
        public static ulong GetBits(string str, string num) {
            var temp = Convert.ToUInt32(num, 16);
            ulong rtemp = 0;
            switch (str)
            {
                case "[31:0]":
                    rtemp = (ulong)temp;
                    break;
                case "[31:9]":
                    rtemp = (ulong)temp >>9;
                    break;
                case "[8]":
                    rtemp = (ulong)temp >> 8 & 0x01;
                    break;
                case "[7:1]":
                    rtemp = (ulong)temp >> 1 & 0x7f;
                    break;
                case "[0]":
                    rtemp = (ulong)temp & 0x01;
                    break;
                case "[31:1]":
                    rtemp = (ulong)temp >> 1;
                    break;
                case "[31]":
                    rtemp = (ulong)temp >> 31;
                    break;
                case "[30]":
                    rtemp = (ulong)temp >> 30 & 0x01;
                    break;
                case "[29]":
                    rtemp = (ulong)temp >> 29 & 0x01;
                    break;
                case "[28]":
                    rtemp = (ulong)temp >> 28 & 0x01;
                    break;
                case "[27]":
                    rtemp = (ulong)temp >> 27 & 0x01;
                    break;
                case "[26]":
                    rtemp = (ulong)temp >> 26 & 0x01;
                    break;
                case "[25]":
                    rtemp = (ulong)temp >> 25 & 0x01;
                    break;
                case "[24]":
                    rtemp = (ulong)temp >> 24 & 0x01;
                    break;
                case "[23]":
                    rtemp = (ulong)temp >> 23 & 0x01;
                    break;
                case "[22]":
                    rtemp = (ulong)temp >> 22 & 0x01;
                    break;
                case "[21]":
                    rtemp = (ulong)temp >> 21 & 0x01;
                    break;
                case "[20]":
                    rtemp = (ulong)temp >> 20 & 0x01;
                    break;
                case "[19]":
                    rtemp = (ulong)temp >> 19 & 0x01;
                    break;
                case "[18]":
                    rtemp = (ulong)temp >> 18 & 0x01;
                    break;
                case "[17]":
                    rtemp = (ulong)temp >> 17 & 0x01;
                    break;
                case "[16]":
                    rtemp = (ulong)temp >> 16 & 0x01;
                    break;
                case "[15]":
                    rtemp = (ulong)temp >> 15 & 0x01;
                    break;
                case "[14]":
                    rtemp = (ulong)temp >> 14 & 0x01;
                    break;
                case "[13]":
                    rtemp = (ulong)temp >> 13 & 0x01;
                    break;
                case "[12]":
                    rtemp = (ulong)temp >> 12 & 0x01;
                    break;
                case "[11]":
                    rtemp = (ulong)temp >> 11 & 0x01;
                    break;
                case "[10]":
                    rtemp = (ulong)temp >> 10 & 0x01;
                    break;
                case "[9]":
                    rtemp = (ulong)temp >> 9 & 0x01;
                    break;
               
                case "[7]":
                    rtemp = (ulong)temp >> 7 & 0x01;
                    break;
                case "[6]":
                    rtemp = (ulong)temp >>6 & 0x01;
                    break;
                case "[5]":
                    rtemp = (ulong)temp >> 5 & 0x01;
                    break;
                case "[4]":
                    rtemp = (ulong)temp >>4 & 0x01;
                    break;
                case "[4:2]":
                    rtemp = (ulong)temp >> 2 & 0x07;
                    break;
                case "[3]":
                    rtemp = (ulong)temp >> 3 & 0x01;
                    break;
                case "[2]":
                    rtemp = (ulong)temp >> 2 & 0x01;
                    break;
                case "[1]":
                    rtemp = (ulong)temp >> 1 & 0x01;
                    break;
                case "[23:16]":
                    rtemp = (ulong)temp >> 16 & 0xff;
                    break;
                case "[15:12]":
                    rtemp = (ulong)temp >> 12 & 0x0f;
                    break;
                case "[7:0]":
                    rtemp = (ulong)temp & 0xff;
                    break;
                case "[31:27]":
                    rtemp = (ulong)temp >> 27;
                    break;
                case "[15:11]":
                    rtemp = (ulong)temp >> 11 & 0x1f;
                    break;
                case "[31:17]":
                    rtemp = (ulong)temp >> 17;
                    break;
                case "[31:22]":
                    rtemp = (ulong)temp >> 22;
                    break;
                case "[21:16]":
                    rtemp = (ulong)temp >> 16 & 0x3f;
                    break;
                case "[15:14]":
                    rtemp = (ulong)temp >> 14 & 0x03;
                    break;
                case "[13:8]":
                    rtemp = (ulong)temp >> 8 & 0x3f;
                    break;
                case "[7:4]":
                    rtemp = (ulong)temp >> 4 & 0x0f;
                    break;
                case "[3:2]":
                    rtemp = (ulong)temp >> 2 & 0x03;
                    break;
                case "[6:4]":
                    rtemp = (ulong)temp >> 4 & 0x07;
                    break;
                case "[31:2]":
                    rtemp = (ulong)temp >> 2;
                    break;
                case "[28:26]":
                    rtemp = (ulong)temp >> 26 & 0x07;
                    break;
                case "[23:12]":
                    rtemp = (ulong)temp >> 12 & 0x7ff;
                    break;
                case "[11:8]":
                    rtemp = (ulong)temp >> 8 & 0x0f;
                    break;
                case "[5:4]":
                    rtemp = (ulong)temp >> 4 & 0x03;
                    break;
                case "[23:0]":
                    rtemp = (ulong)temp & 0xffffff;
                    break;
                case "[25:16]":
                    rtemp = (ulong)temp >> 16 & 0x3ff;
                    break;
                case "[15:8]":
                    rtemp = (ulong)temp >> 8 & 0xff;
                    break;
                case "[9:0]":
                    rtemp = (ulong)temp & 0x3ff;
                    break;
                case "[26:25]":
                    rtemp = (ulong)temp >> 25 & 0x03;
                    break;
                case "[30:24]":
                    rtemp = (ulong)temp >> 24 & 0x7f;
                    break;
                case "[22:16]":
                    rtemp = (ulong)temp >> 16 & 0x7f;
                    break;
                case "[31:28]":
                    rtemp = (ulong)temp >> 28;
                    break;
                case "[27:24]":
                    rtemp = (ulong)temp >> 24 & 0x0f;
                    break;
                case "[19:16]":
                    rtemp = (ulong)temp >> 16 & 0x0f;
                    break;
                case "[31:16]":
                    rtemp = (ulong)temp >> 16;
                    break;
                case "[15:13]":
                    rtemp = (ulong)temp >> 13 & 0x07;
                    break;
                case "[12:8]":
                    rtemp = (ulong)temp >> 8 & 0x1f;
                    break;
                case "[7:6]":
                    rtemp = (ulong)temp >> 6 & 0x03;
                    break;
                case "[1:0]":
                    rtemp = (ulong)temp & 0x03;
                    break;
                case "[20:8]":
                    rtemp = (ulong)temp >> 8 & 0x1fff;
                    break;
                case "[30:28]":
                    rtemp = (ulong)temp >> 28 & 0x07;
                    break;
                case "[26:24]":
                    rtemp = (ulong)temp >> 24 & 0x07;
                    break;
                case "[22:20]":
                    rtemp = (ulong)temp >> 20 & 0x07;
                    break;
                case "[18:16]":
                    rtemp = (ulong)temp >> 16 & 0x07;
                    break;
                case "[14:12]":
                    rtemp = (ulong)temp >> 12 & 0x07;
                    break;
                case "[10:8]":
                    rtemp = (ulong)temp >> 8 & 0x07;
                    break;
                case "[2:0]":
                    rtemp = (ulong)temp & 0x07;
                    break;
                case "[31:8]":
                    rtemp = (ulong)temp >> 8;
                    break;
                case "[31:24]":
                    rtemp = (ulong)temp >> 24;
                    break;
                case "[31:26]":
                    rtemp = (ulong)temp >> 26;
                    break;
                case "[7:5]":
                    rtemp = (ulong)temp >> 5 & 0x07;
                    break;
                case "[16:0]":
                    rtemp = (ulong)temp & 0x1ffff;
                    break;
                case "[23:20]":
                    rtemp = (ulong)temp >> 20 & 0x0f;
                    break;
                case "[17:16]":
                    rtemp = (ulong)temp >> 16 & 0x03;
                    break;
                case "[15:0]":
                    rtemp = (ulong)temp & 0xffff;
                    break;
                case "[25:24]":
                    rtemp = (ulong)temp >> 24 & 0x03;
                    break;
                case "[7:2]":
                    rtemp = (ulong)temp >> 2 & 0x3f;
                    break;
                case "[7:3]":
                    rtemp = (ulong)temp >> 3 & 0x1f;
                    break;
                case "[3:0]":
                    rtemp = (ulong)temp & 0x0f;
                    break;
                case "[5:3]":
                    rtemp = (ulong)temp >> 3 & 0x07;
                    break;
                case "[6:0]":
                    rtemp = (ulong)temp & 0x7f;
                    break;
                case "[4:0]":
                    rtemp = (ulong)temp & 0x1f;
                    break;
                case "[5:0]":
                    rtemp = (ulong)temp & 0x3f;
                    break;
                default:
                    break;
            }
            return rtemp;
        }


        public static ulong SetBitsToUint(string Bits,string Hex, string Val) {
            var valTemp = Convert.ToUInt32(Val, 16);
            var bitsTemp =  Bits.Replace("[", "").Replace("]", "").Split(':');
            //int max = bitsTemp.Max(c => int.Parse(c));
            int min = bitsTemp.Min(c => int.Parse(c));
            //string binary = "";
            //for (int i = 0; i <= max-min; i++)
            //{
            //    binary += "1";
            //}
            //var HexTemp= string.Format("{0:X}", System.Convert.ToInt32(binary, 2));

            return valTemp >> min & Convert.ToUInt32(Hex, 16);
        }
        public static long GetBitsToUint(string Bits, string Hex, string Val)
        {
            var valTemp = Convert.ToUInt32(Val, 16);
            var bitsTemp = Bits.Replace("[", "").Replace("]", "").Split(':');
            //int max = bitsTemp.Max(c => int.Parse(c));
            int min = bitsTemp.Min(c => int.Parse(c));
            //string binary = "";
            //for (int i = 0; i <= max - min; i++)
            //{
            //    binary += "1";
            //}
            //var HexTemp = string.Format("{0:X}", System.Convert.ToInt32(binary, 2));

            return (valTemp >> min)  & Convert.ToUInt32(Hex, 16);
        }
        public static ulong SetBitsCheckedToUint(string Bits,string Hex, string Val,bool isCheck) {
            var valTemp = Convert.ToUInt32(Val, 16);
            var HexTemp = Convert.ToUInt32(Hex, 16);
            if (isCheck)
            {
                return valTemp | HexTemp;
            }
            else {
                return valTemp & (HexTemp ^ 0xff);
            }
        }


        public static long GetBitsCheckedToBool(string Bits,string Hex, string Val) {
            var valTemp = Convert.ToUInt32(Val, 16);
            //var bitsTemp = Bits.Replace("[", "").Replace("]", "").Split(':');
            //int max = bitsTemp.Max(c => int.Parse(c));
            //string binary = "";
            //for (int i = 7; i > -1; i--)
            //{
            //    if (i == max)
            //    {
            //        binary += "1";
            //    }
            //    else
            //    {
            //        binary += "0";
            //    }
            //}
            //var HexTemp = Convert.ToUInt32(string.Format("{0:X}", System.Convert.ToInt32(binary, 2)), 16);
            var HexTemp = Convert.ToUInt32(Hex, 16);
            return ((valTemp & HexTemp) == HexTemp)?0:1;
        }

    
        public static String GetBitsToMask(string Bits, string Bit_Wide,List<string> BList) {
            String maskStr = "";
            double bitNo = 2;
            //try
            //{
                List<string> blArr = new List<string>();
                //解析blist  识别规则  _h高位 _l低位 _m0 。。。_m10 中间位   
                for (int i = 0; i < BList.Count; i++)
                {
                    var blTemp = BList[i].Replace("[", "").Replace("]", "").Split(':');
                    blArr.AddRange(blTemp);
                }
                int max = blArr.Max(c => int.Parse(c));
                int min = blArr.Min(c => int.Parse(c));
                bitNo = Math.Ceiling(((max - min) + 1) / 4.0);
                bitNo = bitNo + (bitNo % 2);
                maskStr = @"[0-9a-fA-F]{1," + $"{(int)bitNo}" + "}";
            //}
            //catch 
            //{
            //    maskStr = @"[0-9a-fA-F]{1,2}";
            //}
            return maskStr;
        }
       
    }

    public class ModelConvertHelper<T> where T : new()
    {
        public static IList<T> ConvertToModel(DataTable dt)
        {
            // 定义集合    
            IList<T> ts = new List<T>();

            // 获得此模型的类型   
            Type type = typeof(T);
            string tempName = "";

            foreach (DataRow dr in dt.Rows)
            {
                T t = new T();
                // 获得此模型的公共属性      
                PropertyInfo[] propertys = t.GetType().GetProperties();
                foreach (PropertyInfo pi in propertys)
                {
                    tempName = pi.Name;  // 检查DataTable是否包含此列    

                    if (dt.Columns.Contains(tempName))
                    {
                        // 判断此属性是否有Setter      
                        if (!pi.CanWrite) continue;

                        object value = dr[tempName];
                        if (value != DBNull.Value)
                            pi.SetValue(t, value, null);
                    }
                }
                ts.Add(t);
            }
            return ts;
        }

        public static DataTable ToDataTable(IEnumerable<T> collection)
        {
            var props = typeof(T).GetProperties();
            var dt = new DataTable();
            dt.Columns.AddRange(props.Select(p => new DataColumn(p.Name, p.PropertyType)).ToArray());
            if (collection.Count() > 0)
            {
                for (int i = 0; i < collection.Count(); i++)
                {
                    ArrayList tempList = new ArrayList();
                    foreach (PropertyInfo pi in props)
                    {
                        object obj = pi.GetValue(collection.ElementAt(i), null);
                        tempList.Add(obj);
                    }
                    object[] array = tempList.ToArray();
                    dt.LoadDataRow(array, true);
                }
            }
            return dt;
        }
    }
}
